using System;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;

using BuildAutoIncrement;

namespace TestUnits {
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    [TestFixture]
    public class AssemblyInfoStreamTest {

        private class TestAssemblyInfoStream : AssemblyInfoStream {
            public TestAssemblyInfoStream(TextReader textReader) {
                m_fileContent = textReader.ReadToEnd();
            }

            public TestAssemblyInfoStream(string content, string filename) {
                m_fileContent = content;
                m_versionPatternProvider = new VersionPatternProvider(Path.GetExtension(filename));
                m_filename = filename;
            }
        }
	
        public AssemblyInfoStreamTest() {
        }

        [SetUp] 
        public void SetUp() {
        }

        [TearDown] 
        public void TearDown() {
        }

        public void TestEntireFilesReading() {
            TestAssemblyInfoStream ais = new TestAssemblyInfoStream(aifVB, "AssemblyInfo.vb");
            AssemblyVersions av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion].ToString() == "1.3.0.13");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);

            ais = new TestAssemblyInfoStream(aifCSharp, "AssemblyInfo.cs");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion].ToString() == "1.3.*");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion].ToString() == "1.3.0.2");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion].ToString() == "1.3.0.1");

            ais = new TestAssemblyInfoStream(aifCpp, "AssemblyInfo.cpp");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion].ToString() == "1.1.0.0");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion].ToString() == "");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion].ToString() == "");

            ais = new TestAssemblyInfoStream(aifJSharp, "AssemblyInfo.jsl");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion].ToString() == "1.0.*");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion].ToString() == "");
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion].ToString() == "");
        }

        public void TestSampleReading() {
            // this is not a valid content
            string content = "  < Assembly: AssemblyVersion(  \"1.3.0.13\"  ) >  \n";
            TestAssemblyInfoStream ais = new TestAssemblyInfoStream(content, "AssemblyInfo.vb");
            AssemblyVersions av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);

            // this is not a valid content
            content = "< Assembly: AssemblyVersion(  \"1.3.0.13\"  ) >  \n";
            ais = new TestAssemblyInfoStream(content, "AssemblyInfo.vb");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);

            // this is valid content
            content = "<Assembly: AssemblyVersion(\"1.3.0.*\")>\n";
            ais = new TestAssemblyInfoStream(content, "AssemblyInfo.vb");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] != ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);

            // this is an invalid content
            content = "<Assembly: AssemblyVersion(\"a.b.c\")>\n";
            ais = new TestAssemblyInfoStream(content, "AssemblyInfo.vb");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] == ProjectVersion.Invalid);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);

            // this is an empty content
            content = "<AssemblyVersion(\"1.2.3\")>\n";
            ais = new TestAssemblyInfoStream(content, "AssemblyInfo.vb");
            av = ais.GetVersions();
            Assert.IsTrue(av[AssemblyVersionType.AssemblyVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyFileVersion] == ProjectVersion.Empty);
            Assert.IsTrue(av[AssemblyVersionType.AssemblyInformationalVersion] == ProjectVersion.Empty);
        }


        #region aifVB AssemblyInfo.vb sample
        private const string aifVB = 
            "Imports System.Reflection Imports System.Runtime.InteropServices\n" +
            "' General Information about an assembly is controlled through the following\n" + 
            "' set of attributes. Change these attribute values to modify the information\n" +
            "' associated with an assembly.\n" +
            "\n" +
            "' Review the values of the assembly attributes\n" +
            "\n" +
            "<Assembly: AssemblyTitle(\"\")> \n" +
            "<Assembly: AssemblyDescription(\"\")> \n" +
            "<Assembly: AssemblyCompany(\"\")> \n" +
            "<Assembly: AssemblyProduct(\"\")> \n" +
            "<Assembly: AssemblyCopyright(\"\")> \n" +
            "<Assembly: AssemblyTrademark(\"\")> \n" +
            "<Assembly: CLSCompliant(True)> \n" +
            "\n" +
            "'The following GUID is for the ID of the typelib if this project is exposed to COM\n" +
            "<Assembly: Guid(\"D5DDC6DC-0188-4CC4-89A6-6C6E8F8EF192\")> \n" +
            "\n" +
            "' Version information for an assembly consists of the following four values:\n" +
            "'\n" +
            "'      Major Version\n" +
            "'      Minor Version \n" +
            "'      Build Number\n" +
            "'      Revision\n" +
            "'\n" +
            "' You can specify all the values or you can default the Build and Revision Numbers \n" +
            "' by using the '*' as shown below:\n" +
            "\n" +
            "<Assembly: AssemblyVersion(\"1.3.0.13\")>\n";
        #endregion aifVB

        #region aifCSharp AssemblyInfo.cs sample
        private const string aifCSharp = 
            "using System.Reflection;\n" + 
            "using System.Runtime.CompilerServices;\n" + 
            "\n" + 
            "//\n" + 
            "// General Information about an assembly is controlled through the following \n" + 
            "// set of attributes. Change these attribute values to modify the information\n" + 
            "// associated with an assembly.\n" + 
            "//\n" + 
            "[assembly: AssemblyTitle(\"\")]\n" + 
            "[assembly: AssemblyDescription(\"\")]\n" + 
            "[assembly: AssemblyConfiguration(\"\")]\n" + 
            "[assembly: AssemblyCompany(\"\")]\n" + 
            "[assembly: AssemblyProduct(\"\")]\n" + 
            "[assembly: AssemblyCopyright(\"\")]\n" + 
            "[assembly: AssemblyTrademark(\"\")]\n" + 
            "[assembly: AssemblyCulture(\"\")]		\n" + 
            "\n" + 
            "//\n" + 
            "// Version information for an assembly consists of the following four values:\n" + 
            "//\n" + 
            "//      Major Version\n" + 
            "//      Minor Version \n" + 
            "//      Build Number\n" + 
            "//      Revision\n" + 
            "//\n" + 
            "// You can specify all the values or you can default the Revision and Build Numbers \n" + 
            "// by using the '*' as shown below:\n" + 
            "\n" + 
            "[assembly: AssemblyVersion(\"1.3.*\")]\n" + 
            "[assembly: AssemblyInformationalVersion(\"1.3.0.1\")]\n" + 
            "[assembly: AssemblyFileVersion(\"1.3.0.2\")]\n" + 
            "\n" + 
            "//\n" + 
            "// In order to sign your assembly you must specify a key to use. Refer to the \n" + 
            "// Microsoft .NET Framework documentation for more information on assembly signing.\n" + 
            "//\n" + 
            "// Use the attributes below to control which key is used for signing. \n" + 
            "//\n" + 
            "// Notes: \n" + 
            "//   (*) If no key is specified, the assembly is not signed.\n" + 
            "//   (*) KeyName refers to a key that has been installed in the Crypto Service\n" + 
            "//       Provider (CSP) on your machine. KeyFile refers to a file which contains\n" + 
            "//       a key.\n" + 
            "//   (*) If the KeyFile and the KeyName values are both specified, the \n" + 
            "//       following processing occurs:\n" + 
            "//       (1) If the KeyName can be found in the CSP, that key is used.\n" + 
            "//       (2) If the KeyName does not exist and the KeyFile does exist, the key \n" + 
            "//           in the KeyFile is installed into the CSP and used.\n" + 
            "//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\n" + 
            "//       When specifying the KeyFile, the location of the KeyFile should be\n" + 
            "//       relative to the project output directory which is\n" + 
            "//       %Project Directory%\\obj\\<configuration>. For example, if your KeyFile is\n" + 
            "//       located in the project directory, you would specify the AssemblyKeyFile \n" + 
            "//       attribute as [assembly: AssemblyKeyFile(\"..\\\\..\\\\mykey.snk\")]\n" + 
            "//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\n" + 
            "//       documentation for more information on this.\n" + 
            "//\n" + 
            "[assembly: AssemblyDelaySign(false)]\n" + 
            "[assembly: AssemblyKeyFile(\"\")]\n" + 
            "[assembly: AssemblyKeyName(\"\")]\n";
        #endregion aifCSharp

        #region aifCpp AssemblyInfo.cpp sample
        const string aifCpp =
            "#include \"stdafx.h\"\n" + 
            "\n" + 
            "#using <mscorlib.dll>\n" + 
            "\n" + 
            "using namespace System::Reflection;\n" + 
            "using namespace System::Runtime::CompilerServices;\n" + 
            "\n" + 
            "//\n" + 
            "// General Information about an assembly is controlled through the following \n" + 
            "// set of attributes. Change these attribute values to modify the information\n" + 
            "// associated with an assembly.\n" + 
            "//\n" + 
            "[assembly:AssemblyTitleAttribute(\"\")];\n" + 
            "[assembly:AssemblyDescriptionAttribute(\"\")];\n" + 
            "[assembly:AssemblyConfigurationAttribute(\"\")];\n" + 
            "[assembly:AssemblyCompanyAttribute(\"\")];\n" + 
            "[assembly:AssemblyProductAttribute(\"\")];\n" + 
            "[assembly:AssemblyCopyrightAttribute(\"\")];\n" + 
            "[assembly:AssemblyTrademarkAttribute(\"\")];\n" + 
            "[assembly:AssemblyCultureAttribute(\"\")];		\n" + 
            "\n" + 
            "//\n" + 
            "// Version information for an assembly consists of the following four values:\n" + 
            "//\n" + 
            "//      Major Version\n" + 
            "//      Minor Version \n" + 
            "//      Build Number\n" + 
            "//      Revision\n" + 
            "//\n" + 
            "// You can specify all the value or you can default the Revision and Build Numbers \n" + 
            "// by using the '*' as shown below:\n" + 
            "\n" + 
            "[assembly:AssemblyVersionAttribute(\"1.1.0.0\")];\n" + 
            "\n" + 
            "//\n" + 
            "// In order to sign your assembly you must specify a key to use. Refer to the \n" + 
            "// Microsoft .NET Framework documentation for more information on assembly signing.\n" + 
            "//\n" + 
            "// Use the attributes below to control which key is used for signing. \n" + 
            "//\n" + 
            "// Notes: \n" + 
            "//   (*) If no key is specified, the assembly is not signed.\n" + 
            "//   (*) KeyName refers to a key that has been installed in the Crypto Service\n" + 
            "//       Provider (CSP) on your machine. KeyFile refers to a file which contains\n" + 
            "//       a key.\n" + 
            "//   (*) If the KeyFile and the KeyName values are both specified, the \n" + 
            "//       following processing occurs:\n" + 
            "//       (1) If the KeyName can be found in the CSP, that key is used.\n" + 
            "//       (2) If the KeyName does not exist and the KeyFile does exist, the key \n" + 
            "//           in the KeyFile is installed into the CSP and used.\n" + 
            "//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\n" + 
            "//        When specifying the KeyFile, the location of the KeyFile should be\n" + 
            "//        relative to the project directory.\n" + 
            "//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\n" + 
            "//       documentation for more information on this.\n" + 
            "//\n" + 
            "[assembly:AssemblyDelaySignAttribute(false)];\n" + 
            "[assembly:AssemblyKeyFileAttribute(\"\")];\n" + 
            "[assembly:AssemblyKeyNameAttribute(\"\")];\n" + 
            "\n";
        #endregion aifCpp AssemblyInfo.cpp sample

        #region aifJSharp AssemlyInfo.jsl sample
        private const string aifJSharp = 
            "import System.Reflection.*;\n" + 
            "import System.Runtime.CompilerServices.*;\n" + 
            "\n" + 
            "//\n" + 
            "// General Information about an assembly is controlled through the following \n" + 
            "// set of attributes. Change these attribute values to modify the information\n" + 
            "// associated with an assembly.\n" + 
            "//\n" + 
            "/** @assembly AssemblyTitle(\"\") */\n" + 
            "/** @assembly AssemblyDescription(\"\") */\n" + 
            "/** @assembly AssemblyConfiguration(\"\") */\n" + 
            "/** @assembly AssemblyCompany(\"\") */\n" + 
            "/** @assembly AssemblyProduct(\"\") */\n" + 
            "/** @assembly AssemblyCopyright(\"\") */\n" + 
            "/** @assembly AssemblyTrademark(\"\") */\n" + 
            "/** @assembly AssemblyCulture(\"\") */\n" + 
            "\n" + 
            "//\n" + 
            "// Version information for an assembly consists of the following four values:\n" + 
            "//\n" + 
            "//      Major Version\n" + 
            "//      Minor Version \n" + 
            "//      Build Number\n" + 
            "//      Revision\n" + 
            "//\n" + 
            "// You can specify all the values or you can default the Revision and Build\n" + 
            "// Numbers by using the '*' as shown below:\n" + 
            "\n" + 
            "/**@assembly AssemblyVersion(\"1.0.*\") */\n" + 
            "\n" + 
            "//\n" + 
            "// In order to sign your assembly you must specify a key to use. Refer to the \n" + 
            "// Microsoft .NET Framework documentation for more information on assembly signing.\n" + 
            "//\n" + 
            "// Use the attributes below to control which key is used for signing. \n" + 
            "//\n" + 
            "// Notes: \n" + 
            "//   (*) If no key is specified, the assembly is not signed.\n" + 
            "//   (*) KeyName refers to a key that has been installed in the Crypto Service\n" + 
            "//       Provider (CSP) on your machine. KeyFile refers to a file which contains\n" + 
            "//       a key.\n" + 
            "//   (*) If the KeyFile and the KeyName values are both specified, the \n" + 
            "//       following processing occurs:\n" + 
            "//       (1) If the KeyName can be found in the CSP, that key is used.\n" + 
            "//       (2) If the KeyName does not exist and the KeyFile does exist, the key \n" + 
            "//           in the KeyFile is installed into the CSP and used.\n" + 
            "//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\n" + 
            "//       When specifying the KeyFile, the location of the KeyFile should be\n" + 
            "//       relative to the project directory. For example, if your KeyFile is\n" + 
            "//       located in the project directory itself, you would specify the\n" + 
            "//       AssemblyKeyFile attribute as @assembly AssemblyKeyFile(\"mykey.snk\")\n" + 
            "//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\n" + 
            "//       documentation for more information on this.\n" + 
            "//\n" + 
            "\n" + 
            "/** @assembly AssemblyDelaySign(false) */\n" + 
            "/** @assembly AssemblyKeyFile(\"\") */\n" + 
            "/** @assembly AssemblyKeyName(\"\") */\n";
        #endregion // aifJSharp AssemlyInfo.jsl sample

    
    }
}
